/**
 * @author Cator Vee  hi@catorv.com
 */
import {forEach, isNumber, isObject} from '../utils'
import {urlDecode, urlEncode} from '../utils/url'

const VERSION = '0'
const CACHE_PREFIX = '~'

const localStorage = window.localStorage

let cookies

// Cookie
export const cookie = {
  get: function (name) {
    if (!cookies) {
      cookies = {}
      const ca = document.cookie.split(';')
      let i = 0
      while (i < ca.length) {
        const c = ca[i++].trim()
        const index = c.indexOf('=')
        cookies[urlDecode(c.slice(0, index))] = urlDecode(c.slice(index + 1))
      }
    }
    return name ? cookies[name] : cookies
  },

  set: function (name, value, duration /* seconds or Date */, path) {
    if (duration) {
      if (isNumber(duration)) {
        duration = new Date(Date.now() + duration * 1000)
      }
      duration = ';expires=' + duration.toGMTString()
    } else {
      duration = ''
    }

    document.cookie = urlEncode(name) + '=' + urlEncode(value) +
      duration + ';path=' + (path || '/')
    cookies = null
  },

  remove: function (name) {
    cookie.set(name, '', -1)
  },

  clear: function () {
    forEach(cookie.get(), (_, name) => {
      cookie.remove(name)
    })
  }
}

// Local Strorage
export const storage = {
  set: function (key, value) {
    if (value == null) { // null or undefined
      storage.remove(key)
    } else {
      localStorage.setItem(key, _encode(value))
    }
  },

  get: function (key) {
    return _decode(localStorage.getItem(key))
  },

  remove: function (key) {
    localStorage.removeItem(key)
  },

  clear: function () {
    localStorage.clear()
  }
}

// Cache
export const cache = {
  set: function (key, data, duration /* seconds */, type) {
    if (isNumber(duration)) {
      duration = _timestamp() + duration
    } else {
      duration = _timestamp(duration)
    }

    let cacheValue = [data, duration]
    if (type) {
      cacheValue.push(type | 0)
    }

    storage.set(CACHE_PREFIX + key, cacheValue)
  },

  get: function (key) {
    const cache = storage.get(CACHE_PREFIX + key)
    const time = _timestamp()

    return (cache && cache[1] > time) ? cache[0] : undefined
  },

  remove: function (key) {
    storage.remove(CACHE_PREFIX + key)
  },

  clearExpired: function (type) {
    cache.clear(type, _timestamp())
  },

  clear: function (type, duration) {
    type |= 0
    duration |= 0

    let key
    let cache
    for (key in localStorage) {
      if (localStorage.hasOwnProperty(key)) {
        if (key[0] === CACHE_PREFIX) {
          cache = storage.get(key)
          if ((type === 0 || type === cache[2]) &&
          (duration === 0 || cache[1] <= duration)) {
            storage.remove(key)
          }
        }
      }
    }
  }
}

try {
  const KEY_VERSION = 'storage-version'
  const localVersion = localStorage.getItem(KEY_VERSION)
  if (localVersion !== null) {
    if (localVersion !== VERSION) {
      cookie.clear()
      storage.clear()
    } else {
      cache.clearExpired()
    }
  }
  localStorage.setItem(KEY_VERSION, VERSION)
} catch (e) {
  // if (e.name == 'QUOTA_EXCEEDED_ERR') {
  //   alert('检测到私密浏览方式已打开，请到设置- safari中关闭私密浏览方式')
  // }
}

function _encode (value) {
  if (isObject(value) || Array.isArray(value)) {
    return '@' + JSON.stringify(value)
  }

  if (isNumber(value)) {
    return '+' + value
  }

  if (value instanceof Date) {
    return '/' + value.getTime()
  }

  if (value === true || value === false) {
    return value ? 'T' : 'F'
  }

  return '"' + value
}

function _decode (value) {
  if (value) {
    const prefix = value[0]
    const text = value.slice(1)
    switch (prefix) {
      case '@':
        return JSON.parse(text)
      case '+':
        return +text
      case '/':
        return new Date(text | 0)
      case 'T':
      case 'F':
        return prefix === 'T'
      case '"':
        return text
      default:
        return value
    }
  }
}

function _timestamp (date) {
  // since Fri Aug 09 2013 15:12:01 GMT+0800 (CST)
  return ((date || Date.now()) / 1000 | 0) - 1376032321
}
